﻿namespace EFS.Common.Async.AsyncResult
{
	/// <summary>
	/// Delegate for async result safe threading
	/// </summary>
	public class StateDelegate
	{
		/// <summary>
		/// AsyncResult deleagte method
		/// </summary>
		/// <param name="ar"></param>
		public delegate void AsyncResultMethod(System.IAsyncResult ar);

		/// <summary>
		/// T method
		/// </summary>
		private AsyncResultMethod asyncResultMethod = null;

		/// <summary>
		/// Pass trough
		/// </summary>
		public System.Object PassTrough { get; private set; }

		/// <summary>
		/// Constructor
		/// </summary>
		/// <param name="asyncResultMethod"></param>
		private StateDelegate(AsyncResultMethod asyncResultMethod)
		{
			// check 
			EFS.Common.Verify.Reference(asyncResultMethod, "asyncResultMethod");

			// set
			this.asyncResultMethod = asyncResultMethod;
		}

		/// <summary>
		/// Constructor
		/// </summary>
		/// <param name="asyncResultMethod"></param>
		private StateDelegate(AsyncResultMethod asyncResultMethod, System.Object passTrough)
		{
			// check 
			EFS.Common.Verify.Reference(asyncResultMethod, "asyncResultMethod");

			// set
			this.asyncResultMethod = asyncResultMethod;
			this.PassTrough = passTrough;
		}

		/// <summary>
		/// Make state object
		/// </summary>
		/// <param name="asyncResultMethod"></param>
		/// <returns></returns>
		public static EFS.Common.Async.AsyncResult.StateDelegate State(AsyncResultMethod asyncResultMethod)
		{
			return new EFS.Common.Async.AsyncResult.StateDelegate(asyncResultMethod);
		}

		/// <summary>
		/// Make state object
		/// </summary>
		/// <param name="asyncResultMethod"></param>
		/// <param name="passTrough"></param>
		/// <returns></returns>
		public static EFS.Common.Async.AsyncResult.StateDelegate State(AsyncResultMethod asyncResultMethod, System.Object passTrough)
		{
			return new EFS.Common.Async.AsyncResult.StateDelegate(asyncResultMethod, passTrough);
		}

		/// <summary>
		/// End asynk
		/// </summary>
		/// <param name="ar"></param>
		public static void End(System.IAsyncResult ar)
		{
			try
			{
				// get state delegate
				EFS.Common.Async.AsyncResult.StateDelegate stateDelegate = (ar.AsyncState as EFS.Common.Async.AsyncResult.StateDelegate);
				EFS.Common.Verify.Reference(stateDelegate, "stateDelegate");

				// call object delegate
				stateDelegate.asyncResultMethod(ar);
			}
			catch (System.Exception ex)
			{
				EFS.EventLog.Log.LogException(ex);
			}
		}
	}
}
